home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Ebooks / Thinking in C++ V2 / C12 / Refcount.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-25  |  2.0 KB  |  80 lines

  1. //: C12:Refcount.cpp
  2. // From Thinking in C++, 2nd Edition
  3. // Available at http://www.BruceEckel.com
  4. // (c) Bruce Eckel 1999
  5. // Copyright notice in Copyright.txt
  6. // Reference count, copy-on-write
  7. #include "../require.h"
  8. #include <cstring>
  9. using namespace std;
  10.  
  11. class Counted {
  12.   class MemBlock {
  13.     static const int size = 100;
  14.     char c[size];
  15.     int refcount;
  16.   public:
  17.     MemBlock() {
  18.       memset(c, 1, size);
  19.       refcount = 1;
  20.     }
  21.     MemBlock(const MemBlock& rv) {
  22.       memcpy(c, rv.c, size);
  23.       refcount = 1;
  24.     }
  25.     void attach() { ++refcount; }
  26.     void detach() {
  27.       require(refcount != 0);
  28.       // Destroy object if no one is using it:
  29.       if(--refcount == 0) delete this;
  30.     }
  31.     int count() const { return refcount; }
  32.     void set(char x) { memset(c, x, size); }
  33.     // Conditionally copy this MemBlock.
  34.     // Call before modifying the block; assign
  35.     // resulting pointer to your block;
  36.     MemBlock* unalias() {
  37.       // Don't duplicate if not aliased:
  38.       if(refcount == 1) return this;
  39.       --refcount;
  40.       // Use copy-constructor to duplicate:
  41.       return new MemBlock(*this);
  42.     }
  43.   }* block;
  44. public:
  45.   Counted() {
  46.     block = new MemBlock; // Sneak preview
  47.   }
  48.   Counted(const Counted& rv) {
  49.     block = rv.block; // Pointer assignment
  50.     block->attach();
  51.   }
  52.   void unalias() { block = block->unalias(); }
  53.   Counted& operator=(const Counted& rv) {
  54.     // Check for self-assignment:
  55.     if(&rv == this) return *this;
  56.     // Clean up what you're using first:
  57.     block->detach();
  58.     block = rv.block; // Like copy-constructor
  59.     block->attach();
  60.     return *this;
  61.   }
  62.   // Decrement refcount, conditionally destroy
  63.   ~Counted() { block->detach(); }
  64.   // Copy-on-write:
  65.   void write(char value) {
  66.     // Do this before any write operation:
  67.     unalias();
  68.     // It's safe to write now.
  69.     block->set(value);
  70.   }
  71. };
  72.  
  73. int main() {
  74.   Counted A, B;
  75.   Counted C(A);
  76.   B = A;
  77.   C = C;
  78.   C.write('x');
  79. } ///:~
  80.